
package JET.Frames.DataModels;

import JET.Centers.ControlCenter;
import JET.Centers.Graphics.GUICenter;
import JET.Scene;
import JET.SwingUtils.TreeUtil;
import JET.UtilPanels.UPSceneInspector;
import JET.physics.engine.JETContext;
import JET.physics.bodies.SpringBody;
import JET.physics.engine.*;
import JET.physics.interfaces.SceneTreeNode;
import java.util.Vector;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 *
 * @author 057Ry
 */
public class SceneTreeModel implements TreeModel {

    static final ControlCenter CC = ControlCenter.getInstance();
    public final SceneRootNode sceneRootNode = new SceneRootNode();
    private Scene scene;
    private Vector<TreeModelListener> treeModelListeners = new Vector<TreeModelListener>();

    public SceneTreeModel() {
    }

    public void setScene(Scene s) {
        scene = s;
    }

    public Object getRoot() {
        if (scene!=null)
            return sceneRootNode;
        else
            return null;
    }

    public Object getChild(Object parent, int index) {
        if (scene!=null)
            return ((SceneTreeNode) parent).getChild(index);
        else
            return null;
    }

    public int getChildCount(Object parent) {
        if (scene!=null)
            return ((SceneTreeNode) parent).getChildCount();
        else
            return 0;
    }

    public boolean isLeaf(Object node) {
        if (scene!=null)
            return ((SceneTreeNode) node).isLeaf();
        else
            return true;
    }

    public void valueForPathChanged(TreePath path, Object newValue) {
        if (scene!=null)
            ((SceneTreeNode) path.getLastPathComponent()).resetNodeValue(newValue);
    }

    public int getIndexOfChild(Object parent, Object child) {
        if (scene!=null)
            return ((SceneTreeNode) parent).getIndexOfChild(child);
        else
            return -1;
    }

    ////////////////////////////////////////////////////////////////////////////
    //                            N O D E S                                   //
    ////////////////////////////////////////////////////////////////////////////

    public class SceneRootNode implements SceneTreeNode {

        public static final int NODE_INDEX_SPRING_BODIES = 0;
        public static final int NODE_INDEX_SPRINGS = 1;
        public static final int NODE_INDEX_RSPRINGS = 2;
        public static final int NODE_INDEX_TORQUES = 3;

        public SceneTreeNode getChild(int index) {
            switch(index) {
                case NODE_INDEX_SPRING_BODIES :
                    return scene.getJETContext().springBodiesTreeNode;
                case NODE_INDEX_SPRINGS :
                    return scene.getJETContext().springsTreeNode;
                case NODE_INDEX_RSPRINGS :
                    return scene.getJETContext().rSpringsTreeNode;
                case NODE_INDEX_TORQUES :
                    return scene.getJETContext().torquesTreeNode;
            }

            return null;
        }

        public int getChildCount() {
            return 4;
        }

        public boolean isLeaf() {
            return false;
        }

        public int getIndexOfChild(Object child) {
            if      (child instanceof SpringBodiesTreeNode) return NODE_INDEX_SPRING_BODIES;
            else if (child instanceof SpringsTreeNode) return NODE_INDEX_SPRINGS;
            else if (child instanceof RSpringsTreeNode) return NODE_INDEX_RSPRINGS;
            else if (child instanceof TorquesTreeNode) return NODE_INDEX_TORQUES;
            else return -1;
        }

        public void resetNodeValue(Object o){}

        @Override
        public String toString() {
            return "Scene";
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //                T R E E   M O D E L   L I S T E N E R S                 //
    ////////////////////////////////////////////////////////////////////////////

    public void addTreeModelListener(TreeModelListener l) {
        treeModelListeners.addElement(l);
    }

    public void removeTreeModelListener(TreeModelListener l) {
        treeModelListeners.removeElement(l);
    }

    ////////////////////////////////////////////////////////////////////////////
    //                     N O T I F I C A T I O N S                          //
    ////////////////////////////////////////////////////////////////////////////

    
    public void fireSpringBodyListChanged() {
        if (scene!=null) {
            TreePath path = new TreePath(new Object[]{  sceneRootNode,
                                                        scene.getJETContext().springBodiesTreeNode,
                                                     });

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }
    
    public void fireSpringBodyChanged(SpringBody sb) {
        if (scene!=null) {
            TreePath path = new TreePath(new Object[]{  sceneRootNode,
                                                        scene.getJETContext().springBodiesTreeNode,
                                                        sb
                                                     });

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }

    public void fireSceneSpringsChanged() {
        if (scene!=null) {
            TreePath path = new TreePath(new Object[]{sceneRootNode,
                                                      scene.getJETContext().springsTreeNode});

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }

    public void fireSceneRSpringsChanged() {
        if (scene!=null) {
            TreePath path = new TreePath(new Object[]{sceneRootNode,
                                                      scene.getJETContext().rSpringsTreeNode});

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }

    public void fireSceneTorquesChanged() {
        if (scene!=null) {
            TreePath path = new TreePath(new Object[]{sceneRootNode,
                                                      scene.getJETContext().torquesTreeNode});

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }

    public void fireWholeTreeChanged() {
        if (scene!=null) {
            SceneTreeNode node = sceneRootNode;
            TreePath path = new TreePath(new Object[]{node});

            JTree sceneTree = ((UPSceneInspector) CC.GUIC.getUtilTab(GUICenter.UtilTabs.SceneInspector)).getSceneTree();
            String sceneTreeExpansionState = TreeUtil.getExpansionState(sceneTree, 0);

            TreeModelEvent evt = new TreeModelEvent(this, path);
            for(TreeModelListener l : treeModelListeners)
                l.treeStructureChanged(evt);

            TreeUtil.restoreExpanstionState(sceneTree, 0, sceneTreeExpansionState);
        }
    }
}
